package com.zlkj.pro.modular.common.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.config.api.context.ConfigContext;
import cn.stylefeng.roses.kernel.file.api.FileOperatorApi;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zlkj.pro.core.exception.BusinessException;
import com.zlkj.pro.modular.common.service.UploadCommonService;
import io.minio.MinioClient;
import io.minio.ObjectWriteArgs;
import io.minio.ObjectWriteResponse;
import io.minio.PutObjectArgs;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;

import static cn.stylefeng.roses.kernel.file.api.constants.FileConstants.FILE_POSTFIX_SEPARATOR;
import static com.zlkj.pro.core.exception.enums.BusinessExceptionEnum.FILE_NAME_CANNOT_BE_EMPTY;

/**
 * @author 孙铭泽
 * @date 2022/3/25
 * @time 17:40
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class UploadCommonServiceImpl implements UploadCommonService {
    private final FileOperatorApi fileOperatorApi;

    private final String bucket = "manbing";

    private final String readUrl = "http://182.92.76.117:9000";
    private final MinioClient minioClient;

    @Override
    public String uploadFile(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isBlank(originalFilename)) {
            throw new BusinessException(FILE_NAME_CANNOT_BE_EMPTY);
        }
        byte[] bytes = file.getBytes();
        String fileBucket = ConfigContext.me().getConfigValueNullable("OSS_ALIYUN_OSS_BUCKET", String.class);
        Long fileId = IdWorker.getId();
        String fileSuffix = StrUtil.subAfter(originalFilename, FILE_POSTFIX_SEPARATOR, true);
        String finalFileName = fileId + FILE_POSTFIX_SEPARATOR + fileSuffix;
        fileOperatorApi.storageFile(fileBucket, finalFileName, bytes);
        String filePath = ConfigContext.me().getConfigValueNullable("OSS_ALIYUN_OSS_DOMAIN_NAME", String.class);
        return String.format("%s/%s", filePath, finalFileName);
    }

    @Override
    public String uploadMinioFile(MultipartFile file) throws Exception {
        String filename = getFileName(file.getOriginalFilename());
        ObjectWriteResponse res = minioClient.putObject(PutObjectArgs.builder()
                .bucket("manbing")
                .object(filename)
                .contentType(file.getContentType())
                .stream(file.getInputStream(), file.getSize(), ObjectWriteArgs.MIN_MULTIPART_SIZE).build());
        // 返回可访问的图片链接
        return readUrl + "/" + bucket + "/" + filename;
    }

    private String getFileName(String filename) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        // 设置存储对象名称
        String dir = sdf.format(new Date());
        int idx = filename.lastIndexOf(".");
        if (idx >= 0) {
            String ext = filename.substring(idx + 1);
            String name = System.currentTimeMillis() + filename.substring(0, idx);
            filename = getMD5(name) + "." + ext;
        }
        return dir + "/" + filename;
    }

    public static String getMD5(String input) {
        try {
            // 获取一个MD5摘要实例
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            byte[] byteArray = input.getBytes("UTF-8");
            md.update(byteArray);
            // 完成哈希计算，得到字节数组形式的哈希值
            byte[] mdBytes = md.digest();

            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (int i = 0; i < mdBytes.length; i++) {
                String hex = Integer.toHexString(0xff & mdBytes[i]);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
